home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Programming Contest / ~Solutions Submitted / Problem 01 - McMullen / Solution.cp < prev    next >
Encoding:
Text File  |  1998-06-19  |  4.1 KB  |  191 lines  |  [TEXT/CWIE]

  1. /*
  2. Problem 01 - Mode Sort
  3.  
  4. This problem is to sort an input string of N characters, N<1000000, based on
  5. the number of times a character occurs in the input.  The most frequently
  6. occurring character should be sorted to the front of the string, followed by
  7. the next most frequently occurring character, etc.  For characters occurring
  8. the same number of times, the character that occurs first in the input should
  9. be sorted to the front.
  10.  
  11. Header specification
  12.  
  13. pascal OSErr ModeSort( const FSSpec* infile, const FSSpec* outfile );
  14.  
  15. Input specification
  16.  
  17. The infile input file contains the characters.  Input characters other than
  18. those printable low ascii characters c, 0x20<c<0x7f, must be ignored.
  19.  
  20. Output specification
  21.  
  22. The outfile must be created and then filled with the sorted characters.  It's
  23. final length should be exactly the same as the count of characters in the
  24. allowed range (0x20<c<0x7f) (which may be shorter than the infile file length).
  25.  
  26. Sample input
  27.  
  28. abcdefghabbcccdddeee
  29. or
  30. 012345678911234567892123456789312345678941234567895123456789612345678971234567891
  31.  
  32. Sample output
  33.  
  34. ccccddddeeeebbbaafgh
  35. or
  36. 111111111122222222233333333344444444455555555566666666677777777788888888999999990
  37. */
  38.  
  39.  
  40. #include <stdlib.h>
  41. #include <string.h>
  42.  
  43. #include "myqsort.h"
  44. #include "Solution.h"
  45.  
  46.  
  47. // Fill in your solution and then submit this folder
  48.  
  49. // Team Name: No. 5
  50.  
  51. #define kFreqArrayLength        (0x7F - 0x20)
  52. #define kCharStart                0x21
  53.  
  54. typedef struct
  55. {
  56.     long            freq;
  57.     unsigned char    order;
  58.     char            theChar;
  59. } TCharFreq;
  60.  
  61.  
  62. static OSErr SortFreqs(void *a, void *b, short *result)
  63. {
  64.     TCharFreq        *first = (TCharFreq *)a;
  65.     TCharFreq        *second = (TCharFreq *)b;
  66.     
  67.     if (second->freq == first->freq)
  68.         *result = (first->order - second->order);
  69.     else
  70.         *result = (second->freq - first->freq);
  71.     return noErr;
  72. }
  73.  
  74. pascal OSErr ModeSort( const FSSpec* infile, const FSSpec* outfile )
  75. {
  76.     short        fileRef = 0;
  77.     short        outFileRef = 0;
  78.     long        fileLength, outDataLength;
  79.     long        i;
  80.     TCharFreq    charFreqs[kFreqArrayLength];
  81.     long        numValidChars = 0;
  82.     Handle        dataHand = nil;
  83.     Handle        outData = nil;
  84.     OSErr        err;
  85.     
  86.     err = FSpOpenDF(infile, fsRdPerm, &fileRef);
  87.     if (err != noErr) return err;
  88.     
  89.     // Get the length of the input file
  90.     err = GetEOF(fileRef, &fileLength);
  91.     if (err != noErr) return err;
  92.     
  93.     // Make a temp handle to hold the data
  94.     dataHand = TempNewHandle(fileLength, &err);
  95.     if (dataHand == nil) return memFullErr;
  96.     
  97.     HLock(dataHand);
  98.     
  99.     err = FSRead(fileRef, &fileLength, *dataHand);
  100.     if (err != noErr) goto exit;
  101.     HUnlock(dataHand);
  102.     
  103.     // zero the freq array
  104.     for (i = 0; i < kFreqArrayLength; i ++)
  105.     {
  106.         charFreqs[i].theChar = kCharStart + i;
  107.         charFreqs[i].order = 0;
  108.         charFreqs[i].freq = 0;
  109.     }
  110.         
  111.     // copy valid chars into the output handle
  112.     {
  113.         char            *src = *dataHand;
  114.         char            *dst = *outData;
  115.         unsigned char    ordinal = 0;
  116.         
  117.         for (i = 0; i < fileLength; i ++)
  118.         {
  119.             if (*src > 0x20 && *src < 0x7F)
  120.             {
  121.                 short    index = *src - kCharStart;
  122.                 
  123.                 // is this a new one?
  124.                 if (charFreqs[index].freq == 0)
  125.                 {
  126.                     charFreqs[index].order = ordinal;
  127.                     ordinal ++;
  128.                 }
  129.                 
  130.                 charFreqs[index].freq ++;
  131.                 
  132.                 numValidChars ++;
  133.             }
  134.             
  135.             *src ++;
  136.         }
  137.         
  138.         outDataLength = dst - *outData;
  139.     }
  140.     
  141.     
  142.     outDataLength = numValidChars;
  143.     outData = TempNewHandle(outDataLength, &err);
  144.     if (outData == nil) return memFullErr;
  145.  
  146.     err = FastQSort(charFreqs, kFreqArrayLength, sizeof(TCharFreq), SortFreqs);
  147.     if (err != noErr) return err;
  148.     
  149.     // dump the freqs into the output handle
  150.     i = 0;
  151.     HLock(outData);
  152.  
  153.     {
  154.         char    *dst = *outData;
  155.         long    j;
  156.         
  157.         do
  158.         {
  159.             for (j = 0; j < charFreqs[i].freq; j ++)
  160.             {
  161.                 *dst ++ = charFreqs[i].theChar;
  162.             }
  163.             
  164.             i ++;
  165.             
  166.         } while (charFreqs[i].freq > 0);
  167.  
  168.     }
  169.     
  170.     // delete the output file
  171.     (void)FSpDelete(outfile);
  172.     
  173.     // create the output file
  174.     err = FSpCreate(outfile, 'CWIE', 'TEXT', smSystemScript);    
  175.     if (err != noErr) return err;
  176.  
  177.     err = FSpOpenDF(outfile, fsRdWrPerm, &outFileRef);
  178.     if (err != noErr) return err;
  179.     
  180.     err = FSWrite(outFileRef, &outDataLength, *outData);
  181.     if (err != noErr) return err;
  182.     DisposeHandle(outData);
  183.     
  184.     err = FSClose(outFileRef);
  185.     
  186. exit:
  187.     if (dataHand != nil)
  188.         DisposeHandle(dataHand);
  189.     return err;
  190. }
  191.